package com.ruoyi.common.utils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.json.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.exception.ServiceException;
import okhttp3.Response;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import static com.ruoyi.common.utils.KeyGenerator.ALGO_EC;

/**
 * Leptage 签名工具
 */
public class LeptageApiSignUtils {

    /**
     * 签名方法
     * @param privateKeyStr
     * @param data
     * @param method
     * @param apiLink
     * @param timeStamp
     * @return
     * @throws Exception
     */
    public static String signData(String privateKeyStr, String data,String method,String apiLink,String timeStamp,String pathParam) {
        String montage = method + apiLink + timeStamp;
        if (pathParam != null && !"".equals(pathParam)) {
            montage = method + apiLink + pathParam + timeStamp;
        }
        if (data != null && !"".equals(data) && !"{}".equals(data)) {
            montage = montage + data;
        }
        System.out.println("签名方法 montage = " + montage);
        byte[] privateKeyBytes = hexStringToByteArray(privateKeyStr);
        // 使用PKCS8EncodedKeySpec将字节数组转换为PrivateKey对象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        try  {
            KeyFactory keyFactory = KeyFactory.getInstance("EC");
            KeyFactory.getInstance(ALGO_EC, new BouncyCastleProvider());
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            // 使用PrivateKey对象进行签名
            Signature signature = Signature.getInstance("SHA256withECDSA");
            signature.initSign(privateKey);
            signature.update(montage.getBytes());
            byte[] signatureBytes = signature.sign();
            return bytesToHex(signatureBytes);
        } catch (Exception e) {
            throw new SecurityException("");
        }
    }

    /**
     * 签名方法
     * @param privateKeyStr
     * @param data
     * @return
     * @throws Exception
     */
    public static String signDataDev(String privateKeyStr, String data) throws Exception {
        // 将私钥字符串解码为字节数组
        byte[] privateKeyBytes = hexStringToByteArray(privateKeyStr);
        // 使用PKCS8EncodedKeySpec将字节数组转换为PrivateKey对象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("EC");
        KeyFactory.getInstance(ALGO_EC, new BouncyCastleProvider());
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        // 使用PrivateKey对象进行签名
        Signature signature = Signature.getInstance("SHA256withECDSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        byte[] signatureBytes = signature.sign();
        return bytesToHex(signatureBytes);
    }

    /**
     * 将字节数组转换为十六进制字符串
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * 将十六进制字符串转换为字节数组
     * @param hex 十六进制字符串
     * @return 字节数组
     */
    public static byte[] hexStringToByteArray(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }

    /**
     * 将对象中的属性参数按照Key的字母顺序重新排列并转成 key=value&key1=value的格式
     * @param obj 对象
     * @return 排序后的字符串
     * @throws IllegalAccessException 如果无法访问对象的属性
     */
    public static String sortAndEncodeParams(Object obj) {
        if (obj == null) {
            return null;
        }
        Map<String, String> params = new HashMap<>();

        // 获取对象的所有字段
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true); // 确保可以访问私有字段
            Object value = null;
            try {
                value = field.get(obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw new ServiceException("无法访问对象的属性");
            }
            if (value != null) {
                params.put(field.getName(), String.valueOf(value));
            }
        }
        // 使用TreeMap来自动排序键
        TreeMap<String, String> sortedParams = new TreeMap<>(params);
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            if (sb.length() > 0) {
                sb.append("&");
            }
            sb.append(entry.getKey()).append("=").append(entry.getValue());
        }
        return sb.toString();
    }

    public static String createSignature(long ts, String url, String body, String secret) {
        Mac hmacSha256;
        byte[] bytes;
        try {
            String content = String.format("%d%s%s", ts, url, body);
            hmacSha256 = Mac.getInstance("HmacSHA256");
            hmacSha256.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            hmacSha256.update(content.getBytes(StandardCharsets.UTF_8));
            bytes = hmacSha256.doFinal();
        } catch (Exception e) {
            throw new RuntimeException("WebhookRequester:createSignature,生成签名异常");
        }
        String signature = HexUtil.encodeHexStr(bytes);
        return signature;
    }

    public static boolean verifySignatures(long ts, String url, String body, String receivedSignature, String secretKey) throws Exception {
        String calculatedSignature = createSignature(ts, url, body, secretKey);
        return calculatedSignature.equals(receivedSignature); // 比较两个签名是否相同
    }

    public static void main(String[] args) throws Exception {
        String bodyStr = "{\"type\":\"WITHDRAW_TXN\",\"data\":{\"txnId\":\"POT1914587529890369536\",\"status\":\"PENDING\",\"createdAt\":1745308213114,\"bene\":{\"destinationAddress\":\"0x0f95fef4bceea6dc2bc2beb7cafe4642e082a9e3\",\"identifier\":{\"company\":{\"companyName\":\"test\"},\"proof\":\"2e5b64dc-6f32-4717-9ebf-5a539ae7424a\"}},\"fee\":{\"money\":{\"ccy\":\"USDT\",\"amount\":\"0.000000\"}},\"payoutMoney\":{\"ccy\":\"USDT\",\"amount\":\"50.000000\"},\"requestId\":\"1112085082522255360\",\"returnFee\":true,\"withdrawalMoney\":{\"ccy\":\"USDT\",\"amount\":\"50.000000\"}}}";
        String sign = "aea64918b817fd2b95a0ef892812bc5ead326faac79e09e92280b961161a7b0d";
        String secretKey = "sbx:xTvWMotsLTvXIoRhNEiZI1TP6KQqD0Z6ZwOJ";
        boolean signatures = verifySignatures(1745308213519L, "http://cwapi.eapjfz.cn/api/third/callback/lpt/tradeConfirm",
            bodyStr, sign, secretKey);
        System.out.println("signatures = " + signatures);
    }
}
